﻿
using System;

using Irony.Compiler;

namespace IronLua.Ast {

	public class BinaryExpression : Expression {

		readonly Expression left;
		readonly Expression right;
		readonly BinaryOperatorType op;

		public Expression Left {
			get { return left; }
		}

		public Expression Right {
			get { return right; }
		}

		public BinaryOperatorType Operator {
			get { return op; }
		}

		public override LuaNodeType NodeType {
			get { return LuaNodeType.BinaryExpression; }
		}

		public BinaryExpression (CompilerContext context, NonTerminal nonTerminal, SourceLocation location, AstNodeList childNodes)
			: base (context, nonTerminal, location, childNodes)
		{
			left = ChildNodes [0].ToExpression ();
			op = GetOperator (ChildNodes [1].Element.Name);
			right = ChildNodes [2].ToExpression ();
		}

		static BinaryOperatorType GetOperator (string op)
		{
			switch (op) {
			case "+":
				return BinaryOperatorType.Add;
			case "and":
				return BinaryOperatorType.And;
			case "/":
				return BinaryOperatorType.Divide;
			case "==":
				return BinaryOperatorType.Equal;
			case ">":
				return BinaryOperatorType.GreaterThan;
			case ">=":
				return BinaryOperatorType.GreaterThanOrEqual;
			case "<":
				return BinaryOperatorType.LessThan;
			case "<=":
				return BinaryOperatorType.LessThanOrEqual;
			case "%":
				return BinaryOperatorType.Modulo;
			case "*":
				return BinaryOperatorType.Multiply;
			case "~=":
				return BinaryOperatorType.NotEqual;
			case "or":
				return BinaryOperatorType.Or;
			case "^":
				return BinaryOperatorType.Power;
			case "-":
				return BinaryOperatorType.Subtract;
			case "..":
				return BinaryOperatorType.Concat;
			default:
				throw new InvalidOperationException ();
			}
		}

		public override void Accept (ILuaAstVisitor visitor)
		{
			visitor.VisitBinaryExpression (this);
		}
	}
}
